//
// Copyright 2011 ReedRex Corp
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// StorageClient.m
// Cloud BookShelf
//
// Created by Shunichi Takagi on 11/02/25.
//

#import "StorageClient.h"


@implementation StorageClient

@synthesize tableServiceURL;
@synthesize blobServiceURL;
@synthesize accountName;
@synthesize accountKey;
@synthesize dateFormatter;

- (NSString *) canonicalizedHeaders:(NSMutableURLRequest *)request {
	NSDictionary *headers = [request allHTTPHeaderFields];
	NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:0];
	
	for(NSString *key in [headers allKeys]){
		if( [key rangeOfString:@"x-ms-" options:NSCaseInsensitiveSearch].location == 0 ) {
			[array addObject:[NSString stringWithFormat:@"%@:%@", [key lowercaseString], [headers valueForKey:key]]];
		}
	}
	
	[array sortUsingSelector:@selector(caseInsensitiveCompare:)];
	
	NSString * canonicalized = @"";
	for(NSString *field in array){
		canonicalized = [canonicalized stringByAppendingFormat:@"%@\n", field];
	}
	
	return canonicalized;
}

- (NSString *) canonicalizedResource:(NSMutableURLRequest *)request {
	return [NSString stringWithFormat:@"/%@%@", self.accountName, [[request URL] path]];
}

- (NSString *) nullToEmpty:(NSString *)msg {
	return ( msg == nil ? @"" : msg );
}

- (id) initWithAccountName:(NSString *)aName andKey:(NSString *)aKey {
	self.tableServiceURL = [NSString stringWithFormat:@TABLE_URL_FORMAT, aName];
	self.blobServiceURL = [NSString stringWithFormat:@BLOB_URL_FORMAT, aName];
	self.accountName = aName;
	self.accountKey = aKey;
	
	self.dateFormatter = [[NSDateFormatter alloc] init];
	
	[dateFormatter setDateFormat:@"EEE',' dd MMM yyyy HH':'mm':'ss 'GMT'"];
	[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]];
	
	return self;
}

- (ObjectContext *) createTableContext {
	AzureTableCredential *cred = [[AzureTableCredential alloc] initWithAccountName:self.accountName accountKey:self.accountKey userPathStyleUrl:YES];
	ObjectContext *ctx = [[ObjectContext alloc] initWithUri:self.tableServiceURL credentials:cred dataServiceVersion:@"1.0"];
	
	[ctx setODataDelegate:self];
	
	return ctx;
}

- (BlobContext *) createBlobContext {
	BlobContext *ctx = [[BlobContext alloc] initWithUri:self.blobServiceURL];
	ctx.delegate = self;
	
	return ctx;
}

- (void) onBeforeSend:(HttpRequest*)request{
	AzureTableUtil *util=[[AzureTableUtil alloc] initWithAccountName:self.accountName accountKey:self.accountKey usePathStyleUri:NO];
	[[request getHeaders] CopyFrom:[util getSignedHeaders:[request getUri]]];
	
	HTTPHeaders *headers = [request getHeaders];
	NSMutableDictionary *dict = [headers GetAll];
	
	for(id key in [dict allKeys]){
		id val = [dict objectForKey:key];
		NSLog(@"%@ : %@", key, val);
	}
	
	NSLog(@"%@", [[NSString alloc] initWithData:[request getBody] encoding:NSASCIIStringEncoding]);
}

-(void) onAfterReceive:(HttpResponse *)response {
	NSMutableDictionary *dict = [response getHeaders];
	for(id key in [dict allKeys]){
		id val = [dict objectForKey:key];
		NSLog(@"%@ : %@", key, val);
	}
	
	NSLog(@"%@", [[NSString alloc] initWithData:[response getBody] encoding:NSASCIIStringEncoding]);
}

- (void) onSendRequest:(NSMutableURLRequest *)request{
	NSString *stringToSign = @"";
	
	[request addValue:@"2009-09-19" forHTTPHeaderField:@"x-ms-version"];
	[request addValue:[self.dateFormatter stringFromDate:[NSDate date]] forHTTPHeaderField:@"x-ms-date"];
	
	stringToSign = [stringToSign stringByAppendingFormat:@"%@\n", [request HTTPMethod]];
	stringToSign = [stringToSign stringByAppendingFormat:@"%@\n", [self nullToEmpty:[request valueForHTTPHeaderField:@"Content-MD5"]]];
	stringToSign = [stringToSign stringByAppendingFormat:@"%@\n", [self nullToEmpty:[request valueForHTTPHeaderField:@"Content-Type"]]];
	stringToSign = [stringToSign stringByAppendingFormat:@"%@\n", [self nullToEmpty:[request valueForHTTPHeaderField:@"Date"]]];
	stringToSign = [stringToSign stringByAppendingFormat:@"%@", [self canonicalizedHeaders:request]];
	stringToSign = [stringToSign stringByAppendingFormat:@"%@", [self canonicalizedResource:request]];
	
	NSLog(@"StringToSign='%@'", stringToSign);
	
	const char *szStringToSign=[stringToSign cStringUsingEncoding:NSASCIIStringEncoding];
	
	NSData *keyData=[Utility Base64Decode:self.accountKey];	
	
	unsigned char hmac[CC_SHA256_DIGEST_LENGTH];
	CCHmac(kCCHmacAlgSHA256,[keyData bytes],[keyData length],szStringToSign,strlen(szStringToSign),hmac);
	
	NSData *HMACdata=[[NSData alloc]initWithBytes:hmac length:sizeof(hmac)];
	
	NSString *signature=[Utility Base64Encode:HMACdata onSeparateLines:YES];
	NSString *authorization = [NSString stringWithFormat:@"SharedKeyLite cirrusfab:%@", signature];
	
	[request addValue:authorization forHTTPHeaderField:@"Authorization"];	
}

@end
